// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#include <nebula/csv/options.h>

namespace nebula::csv {

    ParseOptions ParseOptions::defaults() { return ParseOptions(); }

    turbo::Status ParseOptions::validate() const {
        if (TURBO_UNLIKELY(delimiter == '\n' || delimiter == '\r')) {
            return turbo::invalid_argument_error("ParseOptions: delimiter cannot be \\r or \\n");
        }
        if (TURBO_UNLIKELY(quoting && (quote_char == '\n' || quote_char == '\r'))) {
            return turbo::invalid_argument_error("ParseOptions: quote_char cannot be \\r or \\n");
        }
        if (TURBO_UNLIKELY(escaping && (escape_char == '\n' || escape_char == '\r'))) {
            return turbo::invalid_argument_error("ParseOptions: escape_char cannot be \\r or \\n");
        }
        return turbo::OkStatus();
    }

    ConvertOptions ConvertOptions::defaults() {
        auto options = ConvertOptions();
        // Same default null / true / false spellings as in Pandas.
        options.null_values = {"", "#N/A", "#N/A N/A", "#NA", "-1.#IND", "-1.#QNAN",
                               "-NaN", "-nan", "1.#IND", "1.#QNAN", "N/A", "NA",
                               "NULL", "NaN", "n/a", "nan", "null"};
        options.true_values = {"1", "True", "TRUE", "true"};
        options.false_values = {"0", "False", "FALSE", "false"};
        return options;
    }

    turbo::Status ConvertOptions::validate() const { return turbo::OkStatus(); }

    ReadOptions ReadOptions::defaults() { return ReadOptions(); }

    turbo::Status ReadOptions::validate() const {
        if (TURBO_UNLIKELY(block_size < 1)) {
            // Min is 1 because some tests use really small block sizes
            return turbo::invalid_argument_error("ReadOptions: block_size must be at least 1: ", block_size);
        }
        if (TURBO_UNLIKELY(skip_rows < 0)) {
            return turbo::invalid_argument_error("ReadOptions: skip_rows cannot be negative: ", skip_rows);
        }
        if (TURBO_UNLIKELY(skip_rows_after_names < 0)) {
            return turbo::invalid_argument_error("ReadOptions: skip_rows_after_names cannot be negative: ",
                                   skip_rows_after_names);
        }
        if (TURBO_UNLIKELY(autogenerate_column_names && !column_names.empty())) {
            return turbo::invalid_argument_error(
                    "ReadOptions: autogenerate_column_names cannot be true when column_names are "
                    "provided");
        }
        return turbo::OkStatus();
    }

    WriteOptions WriteOptions::defaults() { return WriteOptions(); }

    turbo::Status WriteOptions::validate() const {
        if (TURBO_UNLIKELY(delimiter == '\n' || delimiter == '\r' || delimiter == '"' ||
                           eol.find(delimiter) != std::string::npos)) {
            return turbo::invalid_argument_error(
                    "WriteOptions: delimiter cannot be \\r or \\n or \" or EOL. Invalid value: ",
                    delimiter);
        }
        if (TURBO_UNLIKELY(batch_size < 1)) {
            return turbo::invalid_argument_error("WriteOptions: batch_size must be at least 1: ", batch_size);
        }
        return turbo::OkStatus();
    }

}  // namespace nebula::csv
